﻿////////////////////////////////////////////////////////////////
///
/// File: Program.cs
/// Author: Cristian Dittamo
/// Last update: 25 March 2010
/// Description: This file contains the definition of the 
///              main classes needed for testing translator execution.
/// To do: 
/// ------------------------------------------------------------
/// Copyright (c) 2009-2010 Cristian Dittamo (dittamo@di.unipi.it)
/// 
/// The use and distribution terms for this software are 
/// contained in the file named license.txt, which can be found 
/// in the root of this distribution.
/// By using this software in any fashion, you are agreeing to 
/// be bound by the terms of this license.
///
/// You must not remove this notice, or any other, from this
/// software.
/// ------------------------------------------------------------
////////////////////////////////////////////////////////////////

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Collections.ObjectModel;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;

using StreamDefs;
using MappedView;
using CLIFile;

using CompileLib.InteropServices;
using CompileLib.InteropServices.NVIDIA;
using CompileLib.Translation;
using CompileLib.Translation.NVIDIA;

using ModelsMapping;
//using MatrixLib;

using PerfCounter;
using Scheduling;
using PerformanceTest.CPU;

namespace Compiler
{
    public class ParAdd
    {
        public ParAdd()
        {
            
        }

        [Kernels]
        public void Add(InputStream<int> input1, InputStream<int> input2, OutputStream<int> output)
        {
            //while (output.MoveNext())
            //{
            //    while (input1.MoveNext())
            //    {
            //        while (input2.MoveNext())
            //        {
            //            output.Current = input1.Current + input2.Current;
            //        }
            //    }
            //}
            /*output.MoveNext();
            input1.MoveNext();
            input2.MoveNext();*/
            output.Current = input1.Current + input2.Current;
        }
    }

    class Program
    {
        static bool CheckCmdLine(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("ERROR - Wrong cmdline - use: Compiler.exe assemblyFile typeFile");
                return false;
            }
            return true;
        }

        /// <summary>
        /// Main program
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            #region Scheduling

            int[] a1 = new int[12000000];
            int[] b1 = new int[12000000];
            int[] c1 = new int[12000000];

            for (int i = 0; i < a1.Length; i++)
                a1[i] = 2;

            for (int i = 0; i < b1.Length; i++)
                b1[i] = 3;

            for (int i = 0; i < c1.Length; i++)
                c1[i] = 0;

            OutputStream<int> output1 = new OutputStream<int>(c1);
            InputStream<int> input1 = new InputStream<int>(a1);
            InputStream<int> input2 = new InputStream<int>(b1);

            //ParAdd p = new ParAdd();
            //double time = p.Add(input1, input2, output1);
            //time *= 12000000;

            Scheduler _scheduler = new Scheduler();
            _scheduler.Schedule(new ParAdd(), "Add", output1, input1, input2);

            Console.WriteLine("Press enter to continue");
            Console.ReadLine();
            return;

            #endregion

            ParAdd pa = new ParAdd();

            int[] a = new int[12];
            int[] b = new int[12];
            int[] c = new int[12];

            for (int i = 0; i < a.Length; i++)
                a[i] = 2;

            for (int i = 0; i < b.Length; i++)
                b[i] = 3;

            for (int i = 0; i < c.Length; i++)
                c[i] = 0;

            GPUDataParallel dp = new GPUDataParallel(new ParAdd());
            OutputStream<int> output = new OutputStream<int>(c);

            dp.Map("Add", output, new InputStream<int>(a), new InputStream<int>(b));

            output.Reset();

            while(output.MoveNext())
                Console.WriteLine(output.Current);

            Console.ReadLine();
        }

        //static public MetaCompute FindType(string assemblyName, string typeName)
        //{
        //    MetaCompute Computation = null;

        //    Assembly file = Assembly.LoadFrom(assemblyName);
        //    CLIFileReader clifile = CLIFileReader.Open(assemblyName);
            
        //    Console.WriteLine("Assembly Loaded: {0}", file.GetName());

        //    //Do not include resource modules
        //    Module[] modules = file.GetModules(false);
        //    Console.WriteLine("Modules:");

        //    for (int mod = 0; mod < modules.Length; mod++)
        //    {
        //        Console.WriteLine("- Name: {0}", modules[mod].Name);
        //        Type[] types = modules[mod].GetTypes();
        //        Console.WriteLine("- #Types: {0}", types.Length);

        //        for (int tp = 0; tp < types.Length; tp++)
        //        {
        //            if (types[tp].Name.CompareTo(typeName) == 0)
        //            {
        //                //Computation = new MetaCUDACompute(types[tp], clifile);

        //                Console.WriteLine("--T-- Name: {0}", types[tp].FullName);
        //                Console.WriteLine("--T-- BaseType: {0}", types[tp].BaseType.FullName);

        //                MethodInfo[] methods = types[tp].GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
        //                Console.WriteLine("--T-- #Methods: {0}", methods.Length);

        //                //MetaCompute Computations = new MetaCompute(types[tp]);

        //                /// 2. found attributed kernel methods
        //                for (int me = 0; me < methods.Length; me++)
        //                {
        //                    object[] attribs = methods[me].GetCustomAttributes(false);
        //                    if (attribs.Length == 0)
        //                        continue;
        //                    Console.WriteLine("----M-- Name: {0}", methods[me].Name);
        //                    Console.WriteLine("----M-- #CustomAttribs: {0}", attribs.Length);
        //                    int KernelAttribIndex = Array.FindIndex<Object>(attribs,
        //                                                             delegate(Object o)
        //                                                             {
        //                                                                 return o.GetType().Equals(typeof(KernelsAttribute));
        //                                                             });
        //                    if (KernelAttribIndex == -1)
        //                        continue;

        //                    // TOOD: ATI case must be considered
        //                    if(Computation == null)
        //                        Computation = new MetaCUDACompute(types[tp], clifile);

        //                    Console.WriteLine("------CA-- Name: {0}", attribs[KernelAttribIndex].ToString());
        //                    IList<CustomAttributeData> cad = CustomAttributeData.GetCustomAttributes(methods[me]);
                            
        //                    // TODO: number of cores as actual parameter of KernelAttribute
        //                    //int cores = System.Environment.ProcessorCount;
        //                    //foreach (CustomAttributeData cdata in cad)
        //                    //{
        //                    //    foreach (CustomAttributeNamedArgument cana in cdata.NamedArguments)
        //                    //    {
        //                    //        /// TODO: Test whether cana.TypedValue is an array or value 
        //                    //        /// TODO: Solve the comparison between strings
        //                    //        Console.WriteLine("--------CAARG-- Type: {0} - Value: {1}", cana.TypedValue.ArgumentType, cana.TypedValue.Value);
        //                    //        if (cana.TypedValue.ArgumentType.ToString().CompareTo("NrTasks") == 0)
        //                    //            cores = (int)cana.TypedValue.Value;
        //                    //    }
        //                    //}

        //                    //Computation.AddKernel(methods[me], cores);
        //                    Computation.AddKernel(methods[me]);
        //                }

        //                return Computation;
        //            }
        //            continue;
        //        }
        //    }
        //    return null;
        //}


    }
}


